package cn.sangedon.review.data.spider.impl;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.sangedon.review.common.domain.data.SpiderMateData;
import cn.sangedon.review.common.domain.data.StockDayInfo;
import cn.sangedon.review.common.service.data.StockDayInfoService;
import cn.sangedon.review.common.service.data.TradingDateService;
import cn.sangedon.review.data.constant.SpiderEnum;
import cn.sangedon.review.data.spider.AbstractStockInfoSpider;
import cn.sangedon.review.data.utils.SpiderUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 深圳日交易Excel数据爬虫
 * Excel数据可一次性获取当日所有交易数据，时间范围可获取三天内
 *
 * @author dongliangqiong
 */
@Slf4j
@Component
public class StockOfDayExcelSzSpider extends AbstractStockInfoSpider {
    @Autowired
    private TradingDateService tradingDateService;

    @Autowired
    private StockDayInfoService stockDayInfoService;

    @Override
    public void runJob(List<SpiderMateData> spiderMateDataList) {
        spiderMateDataList.stream().filter(e -> e.getSpiderName().equals(SpiderEnum.SZ_DAILY_EXCEL_HTTP.getName())).findFirst()
                          .ifPresent(e -> {
                              addSchedule(e);
                          });
    }

    @Override
    public void crawlData() {
        log.info("开始获取深圳交易所日交易Excel数据");
        List<String> tradingDay = tradingDateService.getLatestTradingDay(1);
        long count = stockDayInfoService.count(new LambdaQueryWrapper<StockDayInfo>().eq(StockDayInfo::getTradingDate, tradingDay.get(0))
                                                                                     .likeRight(StockDayInfo::getCode, "00"));
        if (count > 0) {
            log.info("最近交易日{}的深证日交易数据已获取", tradingDay.get(0));
            return;
        }

        processData();
    }

    private void processData() {
        AtomicInteger index = new AtomicInteger(0);
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String today = df.format(new Date());
        while (index.getAndIncrement() < 3) {
            try {
                long preTime = System.currentTimeMillis();
                log.info("第{}次开始获取 {} 日深交所日交易Excel数据", index.intValue(), today);
                String spiderUrl = String.format(getSpiderMateData().getSpiderUrl(), today, today);
                HttpResponse response = HttpRequest.get(spiderUrl).header("Content-Type",
                                                                          "application/vnd.openxmlformats-officedocument.spreadsheetml" +
                                                                          ".sheet;" + "charset=GBK").execute();

                List<StockDayInfo> list = parseExcel(response.bodyStream());
                if (list.size() > 0) {
                    stockDayInfoService.saveOrUpdateBatch(list);
                    log.info("{}日,深交所日交易数据保存成功:{}", today, list.size());
                    index.set(3);
                } else {
                    log.info("{}日，未获取到深证日交易数据", today);
                    ThreadUtil.safeSleep(5 * 60 * 1000);
                }

                Long cost = System.currentTimeMillis() - preTime;
                if (cost < 2000) {
                    SpiderUtil.randomDelay(20);
                }
                log.info("爬取深圳市日交易数据Excel耗时:{}s", cost / 1000);
            } catch (Exception e) {
                log.error("爬取深圳市日交易数据Excel失败:{}", e);
            }
        }
    }

    public List<StockDayInfo> parseExcel(InputStream inputStream) {
        ExcelReader reader = ExcelUtil.getReader(inputStream);
        List<Map<String, Object>> maps = reader.readAll();
        List<StockDayInfo> list = new ArrayList<>();
        for (Map<String, Object> map : maps) {
            StockDayInfo stockDayInfo = new StockDayInfo();
            stockDayInfo.setName(map.get("证券简称").toString());
            stockDayInfo.setCode(map.get("证券代码").toString());
            stockDayInfo.setLastClosePrice(new BigDecimal(map.get("前收").toString().replace(",", "")));
            stockDayInfo.setClosingPrice(new BigDecimal(map.get("今收").toString().replace(",", "")));
            stockDayInfo.setOpeningPrice(new BigDecimal(map.get("开盘").toString().replace(",", "")));
            stockDayInfo.setBottomPrice(new BigDecimal(map.get("最低").toString().replace(",", "")));
            stockDayInfo.setPeakPrice(new BigDecimal(map.get("最高").toString().replace(",", "")));
            stockDayInfo.setChangeRate(new BigDecimal(map.get("涨跌幅（%）").toString().replace(",", "")));
            stockDayInfo.setTradingDate(map.get("交易日期").toString());
            stockDayInfo.setTradingAmount(new BigDecimal(map.get("成交金额(万元)").toString().replace(",", "")));
            Object tradeVolume = map.get("成交量(万股)");
            if (tradeVolume != null && !StringUtils.isEmpty(tradeVolume.toString())) {
                stockDayInfo.setTradingVolume(new BigDecimal(tradeVolume.toString().replace(",", "")).multiply(new BigDecimal(100)));
            }

            stockDayInfo.setChangeAmount(stockDayInfo.getClosingPrice().subtract(stockDayInfo.getOpeningPrice()));
            list.add(stockDayInfo);
        }
        return list;
    }
}
